
#include <QMap>
#include <QString>
#include <QStringList>
#include <QRegExp>
#include <QSharedPointer>
#include <QtTest/QtTest>

#include "Singleton_t.hh"
#include "Options_t.hh"
#include "Misc_t.hh"


namespace {

//! Shared pointer to test suite object
typedef QSharedPointer<QObject> Test_t;

//! Test name -> Test object mapping
typedef QMap<QString, Test_t> TestMap_t;
typedef QMapIterator<QString, Test_t> TestMap_i;
TestMap_t TestMap;


//! Template function to add a test case
template <typename T>
inline void AddTestCase(T* tobj, QString tname, QStringList& targs)
{
  Test_t tptr(tobj);
  tobj->setArgs(targs);
  TestMap.insert(tname, tptr);
}

}


int main(int argc, char* argv[])
{
  QCoreApplication app(argc, argv);
  QStringList args = QCoreApplication::arguments();

  QRegExp flagre("--(\\w+)=(.*)");
  QStringList tc_args;
  QStringList qt_args;

  // Separate QTest arguments out of test class arguments
  QStringListIterator ai(args);
  while(ai.hasNext()) {
    QString item = ai.next();
    if(flagre.exactMatch(item))
      tc_args << item;
    else
      qt_args << item;
  }

  QStringList cases; // Test cases to be executed (regex)
  
  // Process arguments vector to elicit specific test case or
  // function names.
  for(int i=0; i<tc_args.size(); i++) {
    QString flag = tc_args.at(i);
    if(!flagre.exactMatch(flag))
      continue;

    QString fkey = flagre.cap(1);
    QString fval = flagre.cap(2);
    
    if(!fkey.compare("test", Qt::CaseInsensitive)) {
      if(fval.contains(','))
        cases << fval.split(",");
      else 
        cases << fval;
    }

  } // end for

  if(cases.isEmpty())
    cases << "*"; // Add catch-all regex to run all testcases

  
  int rv = 0;
  // Instantiate known test cases
  AddTestCase(new Singleton_t, "Singleton", tc_args);
  AddTestCase(new Options_t, "Options", tc_args);
  AddTestCase(new Misc_t, "Misc", tc_args);

  // Run test cases by looking up desired test cases list
  QStringListIterator si(cases);
  while(si.hasNext()) {
    QRegExp re(si.next(), Qt::CaseInsensitive, QRegExp::Wildcard);
    TestMap_i ti(TestMap);
    while (ti.hasNext()) {
      ti.next();
      if(re.exactMatch(ti.key()))
        rv = QTest::qExec(ti.value().data(), qt_args);
    }
  }

  return rv;
}



